package com.chongchong.online.controller;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chongchong.online.dto.OnlinePageDto;
import com.chongchong.online.entity.*;
import com.chongchong.online.service.*;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.chongchong.common.constant.ErrorCodeEnum;
import com.chongchong.common.tool.CommonUtil;
import com.chongchong.common.validator.AddGroup;
import com.chongchong.common.validator.UpdateGroup;
import com.chongchong.core.mp.object.MyModelUtil;
import com.chongchong.core.mp.object.MyOrderParam;
import com.chongchong.core.mp.object.MyRelationParam;
import com.chongchong.core.mp.support.Condition;
import com.chongchong.core.mp.support.Query;
import com.chongchong.core.tool.api.R;
import com.chongchong.online.dto.OnlineDatasourceDto;
import com.chongchong.online.entity.*;
import com.chongchong.online.entity.constant.PageType;
import com.chongchong.online.object.SqlTable;
import com.chongchong.online.object.SqlTableColumn;
import com.chongchong.online.service.*;
import com.chongchong.online.vo.OnlineDatasourceVo;
import com.chongchong.online.wrapper.OnlineDatasourceWrapper;
import com.chongchong.online.wrapper.OnlineTableWrapper;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.validation.groups.Default;
import java.util.List;

/**
 * 数据模型操作控制器类。
 *
 * @author Jerry
 * @date 2021-06-06
 */
@Api(tags = "数据模型操作接口")
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/onlinedatasource")
public class OnlineDatasourceController {

    private IOnlineDatasourceService onlineDatasourceService;
    private IOnlineFormService onlineFormService;
    private IOnlinePageService onlinePageService;
    private IOnlineTableService onlineTableService;
    private IOnlineDblinkService onlineDblinkService;

    /**
     * 新增数据模型数据。
     *
     * @param onlineDatasourceDto 新增对象。
     * @param onlinePageDto              关联的页面Id。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @ApiOperationSupport(ignoreParameters = {"onlineDatasourceDto.datasourceId"})
    @PostMapping("/save")
    public R<Long> add(
            @RequestBody OnlineDatasourceDto onlineDatasourceDto,
            @RequestBody(required = true) OnlinePageDto onlinePageDto) {
        String errorMessage = CommonUtil.getModelValidationError(onlineDatasourceDto, Default.class, AddGroup.class);
        if (errorMessage != null) {
            return R.fail(errorMessage);
        }
        OnlinePage onlinePage = onlinePageService.getById(onlinePageDto.getPageId());
        if (onlinePage == null) {
            errorMessage = "数据验证失败，页面Id不存在！";
            return R.fail(errorMessage);
        }
        OnlineDatasource onlineDatasource = MyModelUtil.copyTo(onlineDatasourceDto, OnlineDatasource.class);
        OnlineDblink onlineDblink = onlineDblinkService.getById(onlineDatasourceDto.getDblinkId());
        if (onlineDblink == null) {
            errorMessage = "数据验证失败，关联的数据库链接Id不存在！";
            return R.fail(errorMessage);
        }
        SqlTable sqlTable = onlineDblinkService.getDblinkTable(onlineDblink, onlineDatasourceDto.getMasterTableName());
        if (sqlTable == null) {
            errorMessage = "数据验证失败，指定的数据表名不存在！";
            return R.fail(errorMessage);
        }
        // 流程表单的主表主键，不能是自增主键。
        if (onlinePage.getPageType().equals(PageType.FLOW)) {
            for (SqlTableColumn tableColumn : sqlTable.getColumnList()) {
                if (tableColumn.getPrimaryKey()) {
                    if (tableColumn.getAutoIncrement()) {
                        errorMessage = "数据验证失败，流程页面所关联的主表主键，不能是自增主键！";
                        return R.fail(errorMessage);
                    }
                    break;
                }
            }
        }
        onlineDatasource = onlineDatasourceService.saveNew(onlineDatasource, sqlTable, onlinePage.getPageId());
        return R.data(onlineDatasource.getDatasourceId());
    }

    /**
     * 更新数据模型数据。
     *
     * @param onlineDatasourceDto 更新对象。
     * @return 应答结果对象。
     */
    @PostMapping("/update")
    public R<Void> update(@RequestBody OnlineDatasourceDto onlineDatasourceDto) {
        String errorMessage = CommonUtil.getModelValidationError(onlineDatasourceDto, Default.class, UpdateGroup.class);
        if (errorMessage != null) {
            return R.fail(errorMessage);
        }
        OnlineDatasource onlineDatasource = MyModelUtil.copyTo(onlineDatasourceDto, OnlineDatasource.class);
        OnlineDatasource originalOnlineDatasource = onlineDatasourceService.getById(onlineDatasource.getDatasourceId());
        if (originalOnlineDatasource == null) {
            // NOTE: 修改下面方括号中的话述
            errorMessage = "数据验证失败，当前在线数据源并不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        if (!onlineDatasource.getDatasourceId().equals(originalOnlineDatasource.getDatasourceId())) {
            errorMessage = "数据验证失败，不能修改数据库链接Id！";
            return R.fail(errorMessage);
        }
        if (!onlineDatasource.getMasterTableId().equals(originalOnlineDatasource.getMasterTableId())) {
            errorMessage = "数据验证失败，不能修改主表Id！";
            return R.fail(errorMessage);
        }
        if (!onlineDatasourceService.update(onlineDatasource, originalOnlineDatasource)) {
            return R.fail(ErrorCodeEnum.DATA_NOT_EXIST.getErrorMessage());
        }
        return R.data(null);
    }

    /**
     * 删除数据模型数据。
     *
     * @param datasourceId 删除对象主键Id。
     * @return 应答结果对象。
     */
    @PostMapping("/remove")
    public R<Void> delete(@RequestBody Long datasourceId) {
        String errorMessage;
        if (CommonUtil.existBlankArgument(datasourceId)) {
            return R.fail(ErrorCodeEnum.ARGUMENT_NULL_EXIST.getErrorMessage());
        }
        // 验证关联Id的数据合法性
        OnlineDatasource originalOnlineDatasource = onlineDatasourceService.getById(datasourceId);
        if (originalOnlineDatasource == null) {
            errorMessage = "数据验证失败，当前数据源并不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        List<OnlineForm> formList = onlineFormService.getOnlineFormListByDatasourceId(datasourceId);
        if (CollUtil.isNotEmpty(formList)) {
            errorMessage = "数据验证失败，当前数据源正在被 [" + formList.get(0).getFormName() + "] 表单占用，请先删除关联数据！";
            return R.fail(errorMessage);
        }
        if (!onlineDatasourceService.remove(datasourceId)) {
            errorMessage = "数据操作失败，删除的对象不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        return R.data(null);
    }

    /**
     * 列出符合过滤条件的数据模型列表。
     *
     * @param onlineDatasource 过滤对象。
     * @param orderParam                排序参数。
     * @param query                 分页参数。
     * @return 应答结果对象，包含查询结果集。
     */
    @GetMapping("/list")
	public R<IPage<OnlineDatasourceVo>> list(OnlineDatasource onlineDatasource,
											 MyOrderParam orderParam, Query query) {
		String orderBy = MyOrderParam.buildOrderBy(orderParam, OnlineDatasource.class);
		List<OnlineDatasource> onlineDatasourceList =
			onlineDatasourceService.getOnlineDatasourceListWithRelation(onlineDatasource, orderBy);

//		IPage<OnlineTable> pages = onlineTableService.page(Condition.getPage(query), Condition.getQueryWrapper(flowWorkOrder));

		IPage<OnlineDatasource> pages = new Page<>(query.getCurrent(), query.getSize());
		pages.setRecords(onlineDatasourceList);

		return R.data(OnlineDatasourceWrapper.build().pageVO(pages));
	}

	/**
	 * 列出符合过滤条件的数据模型列表。
	 *
	 * @param onlineDatasource 过滤对象。
	 * @return 应答结果对象，包含查询结果集。
	 */
	@GetMapping("/listNoPage")
	public R<List<OnlineDatasourceVo>> listNoPage(OnlineDatasource onlineDatasource) {
		List<OnlineDatasource> onlineDatasourceList = onlineDatasourceService.list(Condition.getQueryWrapper(onlineDatasource));

		return R.data(OnlineDatasourceWrapper.build().listVO(onlineDatasourceList));
	}

    /**
     * 查看指定数据模型对象详情。
     *
     * @param datasourceId 指定对象主键Id。
     * @return 应答结果对象，包含对象详情。
     */
    @GetMapping("/view")
    public R<OnlineDatasourceVo> view(@RequestParam Long datasourceId) {
        if (CommonUtil.existBlankArgument(datasourceId)) {
            return R.fail(ErrorCodeEnum.ARGUMENT_NULL_EXIST.getErrorMessage());
        }
        OnlineDatasource datasource = onlineDatasourceService.getByIdWithRelation(datasourceId, MyRelationParam.full());
        if (datasource == null) {
            return R.fail(ErrorCodeEnum.DATA_NOT_EXIST.getErrorMessage());
        }
        OnlineDatasourceVo onlineDatasourceVo = OnlineDatasourceWrapper.build().entityVO(datasource);

        List<OnlineTable> tableList = onlineTableService.getOnlineTableListByDatasourceId(datasourceId);
        if (CollUtil.isNotEmpty(tableList)) {
            onlineDatasourceVo.setTableList(OnlineTableWrapper.build().listVO(tableList));
        }

        return R.data(onlineDatasourceVo);
    }
}
